package com.fita.admin.service.order.impl;

import com.demo2do.core.entity.exception.BusinessException;
import com.demo2do.core.persistence.annotation.Dao;
import com.demo2do.core.utils.DateFormatUtils;
import com.demo2do.core.utils.StringUtils;
import com.fita.admin.dao.AgentDao;
import com.fita.admin.entity.security.Login;
import com.fita.admin.handler.SmsHandler;
import com.fita.admin.service.DataServiceImpl;
import com.fita.admin.service.ShortUrlService;
import com.fita.admin.service.agent.AgentAuditService;
import com.fita.admin.service.agent.AgentService;
import com.fita.admin.service.order.ReverseOrderService;
import com.fita.admin.utils.ShortUrlUtils;
import com.fita.entity.agent.Agent;
import com.fita.entity.agent.AgentApply;
import com.fita.entity.agent.AgentCompany;
import com.fita.entity.data.ShortUrl;
import com.fita.entity.order.MarkPayRecord;
import com.fita.entity.order.OrderPayType;
import com.fita.entity.order.reverse.ReverseOrder;
import com.fita.entity.order.reverse.ReverseOrderType;
import com.fita.entity.order.reverse.aviation.AviationRequest;
import com.fita.entity.principal.Principal;
import org.hibernate.Session;
import org.hibernate.query.NativeQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: 11200
 * @date: 2019/8/22
 */
@Service("reverseOrderService")
public class ReverseOrderServiceImpl extends DataServiceImpl<ReverseOrder> implements ReverseOrderService {

    private final static Logger logger = LoggerFactory.getLogger(ReverseOrderServiceImpl.class);

    @Autowired
    private SmsHandler smsHandler;

    @Value("#{config['wechat.host']}")
    private String wechatHost;

    @Autowired
    private AgentService agentService;

    @Autowired
    private AgentAuditService agentAuditService;

    @Autowired
    private ShortUrlService shortUrlService;

    @Dao
    private AgentDao agentDao;

    @Value("#{jdbc['payment.database.name']}")
    private String paymentDataBaseName;

    /**
     * 修改价格
     *
     * @param reverseOrderId
     * @param price
     * @param costPrice
     * @param lastPayTime
     */
    public void editPrice(Long reverseOrderId, BigDecimal price, BigDecimal costPrice, Date lastPayTime) {

        ReverseOrder reverseOrder = genericDaoSupport.load(ReverseOrder.class, reverseOrderId);

        reverseOrder.editPrice(price.multiply(new BigDecimal(100)), costPrice.multiply(new BigDecimal(100)), lastPayTime);

        genericDaoSupport.update(reverseOrder);
    }

    /**
     * 发送客户
     *
     * @param reverseOrderId
     */
    public void sendMessageToClient(Long reverseOrderId) {

        ReverseOrder reverseOrder = genericDaoSupport.load(ReverseOrder.class, reverseOrderId);

        String template = "【飞腾会】尊敬的会员您好，您的 [${airline}] 的订单已为您生成，最晚支付时间为 ${lastPayTime}，为保证您顺利出行，请点击[ ${url} ]手机登录后进行支付。";

        Map values = new HashMap();

        values.put("airline", reverseOrder.getAviationBook().getBookAirline());
        values.put("lastPayTime", DateFormatUtils.format(reverseOrder.getLastPayTime(), "yyyy-MM-dd HH:mm:ss"));

        String longUrl = wechatHost + "/reverse-orders/" + reverseOrder.getId() + "?reverseOrderLoginPage=true";

        ShortUrl shortUrl = new ShortUrl(longUrl, ShortUrlUtils.getShortUrl(longUrl), false);

        genericDaoSupport.save(shortUrl);

        values.put("url", wechatHost + "/" + shortUrl.getShortUrl());

        String message = StringUtils.replacePlaceHolder(template, values);

        smsHandler.sendMessage(reverseOrder.getCustomMobile(), message);
    }

    /**
     * 创建代理申请
     *
     * @param reverseOrderId
     * @return
     */
    @Override
    public Long createAgentApply(Long reverseOrderId) {

        ReverseOrder reverseOrder = genericDaoSupport.load(ReverseOrder.class, reverseOrderId);

        if (org.apache.commons.lang3.StringUtils.isBlank(reverseOrder.getCustomMobile())) {
            throw new BusinessException("客户手机号为空，无法创建代理账户");
        }
        if (org.apache.commons.lang3.StringUtils.isBlank(reverseOrder.getCustomName())) {
            throw new BusinessException("客户姓名为空，无法创建代理账户");
        }
        Agent agent = agentService.loadByAgentCompany(reverseOrder.getPrimaryAgentCompany());

        AgentApply secondaryAgentApply = new AgentApply(reverseOrder, agent);

        Long save = (Long) genericDaoSupport.save(secondaryAgentApply);

        return save;
    }

    /**
     * 修改预定
     *
     * @param reverseOrderId
     * @param reverseOrder
     */
    public ReverseOrder editBook(Long reverseOrderId, ReverseOrder reverseOrder) {

        genericDaoSupport.update(reverseOrder);

        return reverseOrder;
    }

    /**
     * 标记支付
     *
     * @param orderId
     * @param payCode
     * @param payTime
     * @param price
     * @param login
     * @param payType
     * @param payPic
     */
    public ReverseOrder markPay(Long orderId, String payCode, Date payTime, BigDecimal price, Login login, OrderPayType payType, String payPic) {

        price = price.multiply(new BigDecimal(100));

        ReverseOrder reverseOrder = genericDaoSupport.load(ReverseOrder.class, orderId);

        if (reverseOrder.isOnlinePay()){
            throw new BusinessException("该订单线上支付过，不能后台标记支付");
        }
        if (!reverseOrder.getStatus().isUnpaid()) {
            throw BusinessException.newInstance("500", "订单状态异常");
        }
        if (!reverseOrder.isNeedPay()) {
            throw BusinessException.newInstance("500", "订单已不需要支付");
        }
        if (reverseOrder.getMarkPayOperator() != null) {
            throw BusinessException.newInstance("500", "订单标记支付人已存在");
        }
        Principal principal = genericDaoSupport.load(Principal.class, login.getId());

        MarkPayRecord markPayRecord = new MarkPayRecord(payType, price, payCode, reverseOrder.getCode(), payTime, principal, payPic);

        genericDaoSupport.save(markPayRecord);

        reverseOrder.markPay(price, payTime);

        genericDaoSupport.update(reverseOrder);

        return reverseOrder;
    }

    /**
     * 取消订单
     *
     * @param orderId
     * @param refundPrice
     * @return
     */
    public ReverseOrder cancel(Long orderId, BigDecimal refundPrice) {

        ReverseOrder reverseOrder = genericDaoSupport.load(ReverseOrder.class, orderId);

        if (refundPrice != null) {
            refundPrice = refundPrice.multiply(new BigDecimal(100));
        }
        if (refundPrice.compareTo(reverseOrder.getActualPayPrice() == null ? BigDecimal.ZERO : reverseOrder.getActualPayPrice()) > 0){
            throw new BusinessException("500", "退款金额大于订单金额");
        }
        reverseOrder.cancel(refundPrice);

        genericDaoSupport.update(reverseOrder);

        return reverseOrder;
    }

    /**
     * 标记出票
     *
     * @param orderId
     * @param orderCode
     * @param ticketTime
     * @return
     */
    public ReverseOrder markTicket(Long orderId, String orderCode, Date ticketTime) {

        ReverseOrder reverseOrder = genericDaoSupport.load(ReverseOrder.class, orderId);

        List<AviationRequest.AviationUserInfo> aviationUserInfos = reverseOrder.getAviationRequest().getAviationUserInfos();
        if (aviationUserInfos == null || aviationUserInfos.size() <= 0) {
            throw new BusinessException("没有成员");
        }
        aviationUserInfos.forEach(aviationUserInfo -> {
            if (!aviationUserInfo.isValid()) {
                throw new BusinessException("成员信息不完整");
            }
        });

        reverseOrder.markTicket(orderCode, ticketTime);


        String template = "【飞腾会】尊敬的会员您好，您的 [${orderCode}] 的订单已出票，详情请戳[ ${url} ]进行查看。";

        Map values = new HashMap();

        values.put("orderCode", reverseOrder.getCode());

        String longUrl = wechatHost + "/reverse-orders/" + reverseOrder.getId() + "?reverseOrderLoginPage=true";

        ShortUrl shortUrl = new ShortUrl(longUrl, ShortUrlUtils.getShortUrl(longUrl), false);

        genericDaoSupport.save(shortUrl);

        values.put("url", wechatHost + "/" + shortUrl.getShortUrl());

        String message = StringUtils.replacePlaceHolder(template, values);

        smsHandler.sendMessage(reverseOrder.getCustomMobile(), message);

        genericDaoSupport.update(reverseOrder);

        return reverseOrder;
    }

    /**
     * 删除
     *
     * @param orderId
     */
    public void delete(Long orderId) {

        ReverseOrder reverseOrder = genericDaoSupport.load(ReverseOrder.class, orderId);

        reverseOrder.delete();

        genericDaoSupport.update(reverseOrder);

    }

    /**
     * 标记核销
     *
     * @param orderId
     * @return
     */
    public ReverseOrder markConsumed(Long orderId) {

        ReverseOrder reverseOrder = genericDaoSupport.load(ReverseOrder.class, orderId);

        reverseOrder.markConsumed(orderId);

        genericDaoSupport.update(reverseOrder);

        return reverseOrder;
    }

    /**
     * 标记退款
     *
     * @param orderId
     * @param refundCode
     */
    public ReverseOrder markRefund(Long orderId, String refundCode) {

        ReverseOrder reverseOrder = genericDaoSupport.load(ReverseOrder.class, orderId);

        reverseOrder.markRefund(refundCode);

        genericDaoSupport.update(reverseOrder);

        return reverseOrder;
    }

    /**
     * 创建订单
     *
     * @param reverseOrderType
     * @param loginId
     * @return
     */
    public ReverseOrder create(ReverseOrderType reverseOrderType, Long loginId) {

        Principal principal = genericDaoSupport.load(Principal.class, loginId);

        ReverseOrder reverseOrder = new ReverseOrder(reverseOrderType, principal);

        genericDaoSupport.save(reverseOrder);

        return reverseOrder;
    }

    /**
     * 修改订单详情
     *
     * @param orderId
     * @param primaryAgentCompanyId
     * @return
     */
    public ReverseOrder editOrderInfo(Long orderId, Long primaryAgentCompanyId) {

        AgentCompany agentCompany = genericDaoSupport.load(AgentCompany.class, primaryAgentCompanyId);

        ReverseOrder reverseOrder = genericDaoSupport.load(ReverseOrder.class, orderId);

        reverseOrder.editOrderInfo(agentCompany);

        genericDaoSupport.update(reverseOrder);

        return reverseOrder;
    }

    /**
     * 验证发送给客户的订单
     *
     * @param reverseOrderId
     * @return
     */
    public ReverseOrder verifySendToClientOrder(Long reverseOrderId) {

        ReverseOrder reverseOrder = genericDaoSupport.load(ReverseOrder.class, reverseOrderId);

        if (!reverseOrder.getStatus().isEditing()) {
            throw new BusinessException("订单不是编辑中状态");
        }
        if (reverseOrder.getPrimaryAgentCompany() == null) {
            throw new BusinessException("一级代理公司为空");
        }
        if (reverseOrder.getAviationBook() == null || !reverseOrder.getAviationBook().isValid()) {
            throw new BusinessException("航班信息不完整");
        }
        if (reverseOrder.getPrice() == null || reverseOrder.getCostPrice() == null || reverseOrder.getLastPayTime() == null) {
            throw new BusinessException("价格信息不完整");
        }
        if (org.apache.commons.lang3.StringUtils.isAnyBlank(reverseOrder.getCustomMobile(), reverseOrder.getCustomName(), reverseOrder.getCustomEmail())) {
            throw new BusinessException("客户信息不完整");
        }
/*        List<AviationRequest.AviationUserInfo> aviationUserInfos = reverseOrder.getAviationRequest().getAviationUserInfos();
        if(aviationUserInfos == null || aviationUserInfos.size() <= 0){
            throw new BusinessException("没有成员");
        }
        aviationUserInfos.forEach(aviationUserInfo -> {
            if (!aviationUserInfo.isValid()){
                throw new BusinessException("成员信息不完整");
            }
        });*/
        return reverseOrder;
    }

    /**
     * @param orderId
     * @param passportPicCode
     * @return
     */
    public AviationRequest.AviationUserInfo loadAviationUserInfo(Long orderId, String passportPicCode) {

        ReverseOrder reverseOrder = genericDaoSupport.load(ReverseOrder.class, orderId);

        List<AviationRequest.AviationUserInfo> aviationUserInfos = reverseOrder.getAviationRequest().getAviationUserInfos();

        if (aviationUserInfos == null || aviationUserInfos.size() <= 0) {

            throw BusinessException.newInstance("500", "成员信息为空");
        }
        List<AviationRequest.AviationUserInfo> matchInfos = aviationUserInfos.stream().filter(c -> c.getPassportPic().equals(passportPicCode)).collect(Collectors.toList());

        if (matchInfos.size() != 1) {
            throw BusinessException.newInstance("500", "数据错误");
        }
        AviationRequest.AviationUserInfo aviationUserInfo = matchInfos.get(0);

        return aviationUserInfo;
    }

    /**
     * 修改
     *
     * @param orderId
     * @param aviationUserInfo
     */
    public void editAviationUserInfo(Long orderId, AviationRequest.AviationUserInfo aviationUserInfo) {

        ReverseOrder reverseOrder = genericDaoSupport.load(ReverseOrder.class, orderId);

        reverseOrder.getAviationRequest().editAviationUserInfo(aviationUserInfo);

        genericDaoSupport.update(reverseOrder);
    }

    /**
     * 添加
     *
     * @param orderId
     * @param aviationUserInfo
     */
    public void addAviationUserInfo(Long orderId, AviationRequest.AviationUserInfo aviationUserInfo) {

        ReverseOrder reverseOrder = genericDaoSupport.load(ReverseOrder.class, orderId);

        if (reverseOrder.getAviationRequest() == null) {

            reverseOrder.setAviationRequest(new AviationRequest());

        }
        reverseOrder.getAviationRequest().addAviationUserInfo(aviationUserInfo);

        genericDaoSupport.update(reverseOrder);

    }

    /**
     * 发送客户
     *
     * @param reverseOrderId
     */
    public void sendToClient(Long reverseOrderId) {

        this.verifySendToClientOrder(reverseOrderId);

        ReverseOrder reverseOrder = genericDaoSupport.load(ReverseOrder.class, reverseOrderId);

        Agent agent = agentDao.loadByMobile(reverseOrder.getCustomMobile());

        if (agent == null) {

            logger.info("prepare create new agent apply.");

            Long agentApplyId = this.createAgentApply(reverseOrderId);

            agentAuditService.verified(agentApplyId);

            agent = agentDao.loadByMobile(reverseOrder.getCustomMobile());

            // 设置默认一级提成
            agent.getCompany().changeCommissionRate(10);
        }
        reverseOrder.sendToClient(agent);

        genericDaoSupport.update(reverseOrder);

        this.sendMessageToClient(reverseOrderId);
    }

    /**
     * @param orderId
     * @param resetPrice
     * @param costPrice
     * @param lastPayTime
     * @return
     */
    public ReverseOrder resetPrice(Long orderId, BigDecimal resetPrice, BigDecimal costPrice, Date lastPayTime) {

        ReverseOrder reverseOrder = genericDaoSupport.load(ReverseOrder.class, orderId);

        resetPrice = resetPrice.multiply(new BigDecimal(100));

        costPrice = costPrice.multiply(new BigDecimal(100));

        reverseOrder.resetPrice(resetPrice, costPrice, lastPayTime);

        genericDaoSupport.update(reverseOrder);

        String template = "【飞腾会】尊敬的会员您好，您的[${ariline}]的订单价格已更新，最晚支付时间为 ${lastPayTime}，为保证您顺利出行，请点击[ ${url} ]登录后进行支付。";

        Map values = new HashMap();

        values.put("ariline", reverseOrder.getAviationBook().getBookAirline());

        values.put("lastPayTime", DateFormatUtils.format(reverseOrder.getLastPayTime(), "yyyy-MM-dd HH:mm:ss"));

        String longUrl = wechatHost + "/reverse-orders/" + reverseOrder.getId();

        ShortUrl shortUrl = new ShortUrl(longUrl, ShortUrlUtils.getShortUrl(longUrl), false);

        genericDaoSupport.save(shortUrl);

        values.put("url", wechatHost + "/" + shortUrl.getShortUrl());

        smsHandler.sendMessage(reverseOrder.getCustomMobile(), template, values);

        return reverseOrder;
    }

    /**
     * 删除乘机人
     *
     * @param orderId
     * @param picCode
     */
    public void deleteAviationUserInfo(Long orderId, String picCode) {

        ReverseOrder reverseOrder = genericDaoSupport.load(ReverseOrder.class, orderId);

        reverseOrder.getAviationRequest().removeAviationUserInfo(picCode);

        genericDaoSupport.update(reverseOrder);
    }

    /**
     * @param code
     * @return
     */
    public List<Object[]> listPaymentContext(String code) {

        Session session = genericDaoSupport.getCurrentSession();

        NativeQuery nativeQuery = session.createNativeQuery("SELECT * FROM `" + paymentDataBaseName + "`.tbl_payment_context WHERE order_code = :orderCode AND status = 1");

        nativeQuery.setParameter("orderCode", code);

        List list = nativeQuery.list();

        return list;
    }
}
